#include "WiFi.h"                                                                     //导入WiFi库
#include "BluetoothSerial.h"                                                          //导入蓝牙库
#include "PubSubClient.h"
#include <MySQL_Generic.h>                                                         // Arduino连接Mysql的库


#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)                 //编译处理指令
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

BluetoothSerial SerialBT;                                                             //蓝牙串口
WiFiClient espClient;                                                                 //定义wifiClient实例

PubSubClient client(espClient);//定义PubSubClient的实例

MySQL_Connection conn((Client *)&MySqlClient);
MySQL_Query *query_mem;

void BTFI();
void MQTTConnect();
void readAndRecordData();
void mySqlInit();

const char * mqttServer = "000.000.000.000";                                          //要连接到的MQTT服务器IP
const int mqttPort =1883;                                                             //要连接到的服务器端口号
const char * mqttUser = "admin";                                                      //MQTT服务器账号
const char * mqttPassword = "public";                                                 //MQTT服务器密码

IPAddress server_addr(000,000,000,000);                                               //Mysql服务器的地址
uint16_t server_port = 3306;    //3306;
char user[] = "username";                                                          //Mysql的用户名
char password[] = "password";                                                      //登陆Mysql的密码
char database[] = "database";

char INSERT_SQL[] = "INSERT INTO  database.table(TEM,WATER,ATTITUDE,SUB_DATE) VALUES ('%s','%s','%s',NOW())";


char buff[128];                                                                       //定义存储传感器数据的数组(SQL也将保存在这里)
char tem[5];      
char water[5];
char attitude[10];
bool temFlag = 0, waterFlag = 0, attitudeFlag = 0;

String tempString = "";                                                               //公共缓冲区
int MQTTindex = 0;

void setup()
{
  Serial2.begin(9600);
  Serial.begin(115200);
  SerialBT.begin("DE_ForESP32");                                                      //蓝牙设备名称
  BTFI();
  MQTTConnect();
}

void loop()
{
  char buf[25] = {};
  MQTTindex = 0;
  while (Serial.available() > 0)                                                        //蓝牙串口接收
  {
    tempString += char(Serial.read());                                                  //放入字符串缓冲区
    delay(2);                                                                           //延时存放
  }
  if (tempString.indexOf("tem:") != -1)                                                      
  {
    MQTTindex = tempString.indexOf("tem:");
    strcpy(buf, tempString.substring(MQTTindex + 4, tempString.length()).c_str());
    strcpy(tem, buf);                                                                   //温度数据存入tem[]
    temFlag = 1;
    client.publish("tem",buf);                                                          //向MQTT服务器发送的信息(主题，内容)
  }
  else if (tempString.indexOf("water:") != -1)                                                
  {
    MQTTindex = tempString.indexOf("water:");
    strcpy(buf, tempString.substring(MQTTindex + 6, tempString.length()).c_str());
    strcpy(water, buf);
    waterFlag = 1;
    client.publish("water",buf);                                                         //向MQTT服务器发送的信息(主题，内容)
  }
  else if (tempString.indexOf("attitude:") != -1)                                                
  {
    MQTTindex = tempString.indexOf("attitude:");
    strcpy(buf, tempString.substring(MQTTindex + 9, tempString.length()).c_str());
    strcpy(attitude, buf);
    attitudeFlag = 1;
    client.publish("attitude:",buf);                                                     //向MQTT服务器发送的信息(主题，内容)
  }
  if (temFlag == 1 && waterFlag == 1 && attitudeFlag == 1)
  {
    temFlag = 0;
    waterFlag = 0;
    attitudeFlag = 0;
    mySqlInit();
  }
  tempString = "";
  client.loop();                                                                         //保持监听防止超时
}

void mySqlInit()
{
  if (conn.connectNonBlocking(server_addr, server_port, user, password) != RESULT_FAIL)
  {
    delay(500);
    readAndRecordData();
    conn.close();                     // close the connection
  } 
  else 
  {
    Serial.println("\nConnect failed. Trying again on next iteration.");
  }

}

void readAndRecordData()
{
  // Initiate the query class instance
  sprintf(buff,INSERT_SQL,tem,water,attitude);                                           // 数据放入SQL中
  MySQL_Query query_mem = MySQL_Query(&conn);

  if (conn.connected())
  {
    Serial.println(buff);
    
    // Execute the query
    // KH, check if valid before fetching
    if ( !query_mem.execute(buff))
    {
      Serial.println("Insert error");
    }
    else
    {
      Serial.println("Data Inserted.");
    }
  }
  else
  {
    Serial.println("Disconnected from Server. Can't insert.");
  }                                                                      // 删除mysql实例为下次采集作准备
}


void BTFI()
{
  /************************************************************************************************
  *变量：ssid -> WiFi名称
  *     password -> WiFi密码
  ***********************************************************************************************/
  String ssid = "";
  String password = "";
  bool WiFiFlag = 0;                                                                    //第一次连接标志
  while (ssid.length() == 0 || password.length() == 0)                                  //判断用于存储wifi名称和密码的字符串为空
  {
    while (SerialBT.available() > 0)                                                    //蓝牙串口接收
    {
      tempString += char(SerialBT.read());                                              //放入字符串缓冲区
      delay(2);                                                                         //延时存放
    }
    if (tempString.length() > 0)                                                        //存放完毕
    {
      /*Serial.print("tempString is :");
      Serial.println(tempString);*/
      if (tempString.indexOf("ssid:") != -1 && tempString[0] == 's')                    //截取字符串判断信息是否为ssid并且由于先后顺序需要判断密码中不含ssid:
      {
        int indexOfSsid = tempString.indexOf("ssid:");
        /*Serial.print("indexOfSsid = ");
        Serial.println(indexOfSsid);*/
        ssid = tempString.substring(indexOfSsid + 5, tempString.length());              //截取存放
        Serial.print("ssid is :");
        Serial.println(ssid);
      }
      else if (tempString.indexOf("password:") != -1 && tempString[0] == 'p')
      {
        int indexOfPassword = tempString.indexOf("password:");
        /*Serial.print("indexOfPassword = ");
        Serial.println(indexOfPassword);*/
        password = tempString.substring(indexOfPassword + 9, tempString.length());
        Serial.print("password is :");
        Serial.println(password);
      }
    }
    tempString = "";
    delay(20);
  }
  while (!WiFiFlag)
  {
     char sid[25];                                                                        //WiFi.begin函数中需要填入char[]而Arduino中的String是class
     strcpy(sid, ssid.c_str());
     char pswd[25];
     strcpy(pswd, password.c_str());
     Serial.println("Bluetooth init is over ssid and password:");
     Serial.print(ssid);
     Serial.print(" / ");
     Serial.println(password);
     WiFi.begin(sid, pswd);
     while (WiFi.status() != WL_CONNECTED)                                                //等待连接wifi输出信息
     {
        delay(200);
        Serial.print(".");
     }
     Serial.println("WiFi connected!");
     Serial.print("ip is :");
     Serial.println(WiFi.localIP());
     WiFiFlag = 1;                                                                        //更改标志信息，防止重复连接
  }
}


void MQTTConnect()
{
  client.setServer(mqttServer,mqttPort);                                              //MQTT服务器连接函数（服务器IP，端口号）
  while (!client.connected())                                                         //是否连接上MQTT服务器
  {
    if (client.connect("DE_ForESP32"))                                                //如果服务器连接成功
    {
        Serial.println("MQTT Connected!");
    }
    else 
    {
        Serial.print(client.state());                                                 //重新连接函数
        delay(2000);                        
    }
  }
}
